package org.jiucheng.magpiebridge.transfer.aio;

import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler;
import java.nio.channels.SocketChannel;

import org.jiucheng.magpiebridge.protocol.Message;

/**
 * 
 * @author jiucheng
 *
 */
public class TransferReadCompletionHandler implements CompletionHandler<Integer, TransferAttachment> {

	public void completed(Integer result, TransferAttachment attachment) {
        // client关闭连接
        if (result == -1) {
            // close(attachment);
        	attachment.close();
            return;
        }
        ByteBuffer readByteBuffer = attachment.getReadByteBuffer();
        if (readByteBuffer.position() != readByteBuffer.capacity()) {
            attachment.getClient().read(readByteBuffer, attachment, this);
            return;
        }
        if (readByteBuffer.capacity() == 13) {
            // 验证消息头
            readByteBuffer.flip();
            int magic = readByteBuffer.getInt();
            byte type = readByteBuffer.get();
            int uri = readByteBuffer.getInt();
            int size = readByteBuffer.getInt();
            if (magic != Message.MAGIC) {
                // close(attachment);
            	attachment.close();
                return;
            }
            if (size > 0) {
                readByteBuffer = ByteBuffer.allocate(size + 13);
                readByteBuffer.putInt(magic);
                readByteBuffer.put(type);
                readByteBuffer.putInt(uri);
                readByteBuffer.putInt(size);
                attachment.getClient().read(readByteBuffer, attachment.setReadByteBuffer(readByteBuffer), this);
                return;
            }
        }
		
        Message message = Message.fromByteBuffer(readByteBuffer);
        byte type = message.getType();
        if (type == Message.Type.TRANSFER) {
			handleTransferMessage(attachment, message);
        } else if (type == Message.Type.HEARTBEAT) {
        	// 心跳不处理
            attachment.setReadByteBuffer(ByteBuffer.allocate(13));
            attachment.getClient().read(attachment.getReadByteBuffer(), attachment, this);
        }
	}
	
    private void handleTransferMessage(TransferAttachment attachment, final Message message) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(message.getData().length);
        byteBuffer.put(message.getData());
        byteBuffer.flip();
        SocketChannel socket = attachment.getRealSocketChannel();
        if (socket != null) {
            try {
                while(byteBuffer.hasRemaining()) {
                    socket.write(byteBuffer);
                }
                attachment.setReadByteBuffer(ByteBuffer.allocate(13));
                attachment.getClient().read(attachment.getReadByteBuffer(), attachment, this);
            } catch (Exception e) {
                Message rmsg = new Message();
                rmsg.setMagic(Message.MAGIC);
                rmsg.setType(Message.Type.DISCONNECT);
                rmsg.setUri(message.getUri());
                ByteBuffer buffer = Message.toByteBuffer(rmsg);
                if (attachment.canWrited()) {
                    attachment.getClient().write(buffer, attachment.setWriteByteBuffer(buffer), new TransferWriteCompletionHandler());
                }
            }
        }
    }

	public void failed(Throwable exc, TransferAttachment attachment) {
		attachment.close();
	}
}
